package ClassificationAlgorithm;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Random;

import Definitions.GraphClass;
import Definitions.NodeClass;
import Global.ConstantVariable;
import Global.GlobalClass;
import Global.ParametersClass;
import LocalClassifier.LocalClassifierInterface;
import Result.ResultClass;
import Result.ResultIdentificationClass;
import Sampling.SamplingAbstractClass;



public abstract class CCAClass implements CollectiveClassificationAlgorithmClass 
{

	Random random ;
	String name;
	GraphClass graph;
	GlobalClass global;
	LocalClassifierInterface localClassifierSelected;
	SamplingAbstractClass usedSampling;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//Bu yeni 
	CCAClass(GraphClass graph, GlobalClass global, LocalClassifierInterface localClassifier, SamplingAbstractClass sampling)
	{
		this.graph = graph;
		this.global = global;
		this.localClassifierSelected = localClassifier;
		this.usedSampling = sampling;
	}	
	
	
	/*****************************************************************
	* Function Name: 	CCA (Constructor)
	* Aim: 				create the "random" 
	* Inputs: 			---
	* Outputs: 			---
	* Data Structures:  ---
	* Algorithms: 		---
	*****************************************************************/
	CCAClass(GraphClass graph, GlobalClass global, LocalClassifierInterface localClassifier, String name)
	{		
		this.graph = graph;
		this.global = global;
		this.localClassifierSelected = localClassifier;
		this.name = name;
		
		random = new Random();
	}

	public void Run(SamplingAbstractClass currentSampling, ResultClass result)
	{
		
	}
	
	 public int [] initializeOrderArray(int size)
	 {
		 int [] orderArray = new int[size];
		 for(int i: orderArray)
		 {
			orderArray[i] = i; 
		 }
		 return orderArray;
	 }
	
	/*****************************************************************
	* Function Name: 	reORder
	* Aim: 				generate the shulffed list
	* Inputs: 			get the order array list
	* Outputs: 			no output change the list of array
	* Data Structures:  ---
	* Algorithms: 		---
	*****************************************************************/
	public void  reOrder(int nodeOrderList[]) 
	{	
		int size=nodeOrderList.length;
		for(int i= 0; i<size ; i++)
		{
			int index1=random.nextInt(size);
			int index2=random.nextInt(size);
			int temp= nodeOrderList[index1];
			nodeOrderList[index1]= nodeOrderList[index2];
			nodeOrderList[index2] =temp;
		}
	}	
	public void write(double start, double end , String fileName)
	{
		try{
			
		    /* for arranging file name adding some additional informations*/
			String fileAdditionalProperties= "file"; //"typeofCCA " +ParametersClass.typeOfCCA + " iter-"+ParametersClass.iteration+"-dataset-"+ParametersClass.typeOfDataSet+"-Sampling-";
			FileWriter fstream = new FileWriter(fileAdditionalProperties);
		    BufferedWriter out = new BufferedWriter(fstream);
		    
		    /* for writing all test nodes to file actual labels */
			
		    start*=10000;
		    end  *=10000;
		    out.newLine();
		    out.write("Start : "+start);
		    out.newLine();
		    out.write("End : "+end);
		    out.newLine();
		    out.newLine();
	    //Close the output stream	
			
	    out.close();
		}
		catch (Exception e)
		{//Catch exception if any
	      System.err.println("Error: " + e.getMessage());
		}
	}
	
	public ResultClass TrainForGlobalAlpha(GraphClass graph, GlobalClass global, SamplingAbstractClass prevSampling,int foldNo)
	{
		try{
		System.out.println("Starting train for Alpha ");
		
		String datasetName =ConstantVariable.DataSet_Constants.DATASET_NAMES[GlobalClass.RunningValues.executionFor];
		String CCA_Name = ConstantVariable.CCA_ConstantVariables.CONTENT_ONLY;
		String samplingName = ConstantVariable.Sampling_Constants.SNOWBALL_SAMPLING_METHOD;
						
		ResultIdentificationClass identifier = new ResultIdentificationClass();
		identifier.setDataset(datasetName);
		identifier.setCCA(CCA_Name);
		identifier.setSampling(samplingName);
		identifier.setFold(foldNo);
		
		ResultClass result = new ResultClass(identifier);
		System.out.println("Fold :  " + foldNo);
				 
		localClassifierSelected.initialize(graph, result);
		localClassifierSelected.train(graph);
		return result;
		}
		catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}
	
	public ResultClass TrainForLocalAlpha(ArrayList<NodeClass> nodeListForTrain, int foldNo, SamplingAbstractClass currentSampling)
	{
		try{
		System.out.println("Starting train for Alpha ");
		
		String datasetName =ConstantVariable.DataSet_Constants.DATASET_NAMES[GlobalClass.RunningValues.executionFor];
		String CCA_Name = ConstantVariable.CCA_ConstantVariables.CONTENT_ONLY;
		String samplingName = ConstantVariable.Sampling_Constants.SNOWBALL_SAMPLING_METHOD;
						
		ResultIdentificationClass identifier = new ResultIdentificationClass();
		identifier.setDataset(datasetName);
		identifier.setCCA(CCA_Name);
		identifier.setSampling(samplingName);
		identifier.setFold(foldNo);
		
		ResultClass result = new ResultClass(identifier);
		result.setSampling(currentSampling);
		System.out.println("Fold :  " + foldNo);
				 
		localClassifierSelected.initialize(graph, result);
		localClassifierSelected.train(graph);
		return result;
		}
		catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}
	
	public ResultClass TestWithForAlpha(ArrayList<NodeClass> nodeListToBeTested, SamplingAbstractClass prevSampling, ResultClass result, int foldNo)
	{		
		//First label assignments to test dataset
		for(NodeClass i : nodeListToBeTested)
		{
			localClassifierSelected.evaluate(i, ConstantVariable.Sampling_Constants.NODE_IS_IN_TEST_SET_FOR_THE_FOLD, ConstantVariable.LocalClassifier_Constants.SOFT);
			//System.out.println( currentSampling.getTestNodes().get(i).getClassOrder() +"  " + currentSampling.getTestNodes().get(i).getPredictClassOrder() );
		}
		//System.out.println("Alpha Test Only:   "+ Evaluation.findTotalAccuracy(Evaluation.CreateConfMat(nodeListToBeTested)));

		return result;
	}
	
	public 	double[] TestNodeForAlpha(NodeClass nodeToBeTested, SamplingAbstractClass prevSampling, int foldNo)
	{		

		//First label assignments to test dataset
		return localClassifierSelected.evaluate(nodeToBeTested, ConstantVariable.Sampling_Constants.NODE_IS_IN_TEST_SET_FOR_THE_FOLD, ConstantVariable.LocalClassifier_Constants.SOFT);
			//System.out.println( currentSampling.getTestNodes().get(i).getClassOrder() +"  " + currentSampling.getTestNodes().get(i).getPredictClassOrder() );
		
		//System.out.println("Alpha Test Only:   "+ Evaluation.findTotalAccuracy(Evaluation.CreateConfMat(nodeListToBeTested)));
		
	}
	
	public double[] getProbabilityDistributionForTheGivenNode(NodeClass nodeToBeTested)
	{		
		return localClassifierSelected.evaluate(nodeToBeTested, ConstantVariable.Sampling_Constants.NODE_IS_IN_TEST_SET_FOR_THE_FOLD, ConstantVariable.LocalClassifier_Constants.SOFT);
			//System.out.println( currentSampling.getTestNodes().get(i).getClassOrder() +"  " + currentSampling.getTestNodes().get(i).getPredictClassOrder() );
	}
	
	public LocalClassifierInterface getLocalClassifierSelected()
	{
		return localClassifierSelected;
	}
}
	

